package com.blockmeta.bbs.businesslibrary.websocket;

import android.os.Handler;


import com.blockmeta.bbs.baselibrary.utils.TimeUtil;
import com.blockmeta.bbs.businesslibrary.pojo.websocket.BasePOJO;

import org.greenrobot.eventbus.Subscribe;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import buf.Return;


/**
 * 需要等待status ack的序列物件
 *
 */
public class WaitSendQueue
{
	protected ConcurrentHashMap<Integer, Packet>	m_mapPacket;
	protected Handler 			m_hanlder;
	protected ArrayList<Packet> m_arTimeoutPacket;
	protected int m_nTimeout = 0;
	protected ConnectManager m_connManager;

	public WaitSendQueue(ConnectManager mgr)
	{
        m_hanlder   = new Handler();
		m_mapPacket = new ConcurrentHashMap<Integer, Packet>();
		m_arTimeoutPacket = new ArrayList<Packet>();

		m_connManager = mgr;
		if(!ConnectCenter.getConnectCenter().isRegistered(this)) {
			ConnectCenter.getConnectCenter().register(this);
		}

	}
	
	protected void clear()
	{
		m_mapPacket.clear();
	}
	
	protected Runnable	m_run = new Runnable() 
	{

		@Override
		public void run() 
		{			
			Iterator iter = m_mapPacket.entrySet().iterator();
			
			while(iter.hasNext())
			{
				Map.Entry pairs = (Map.Entry)iter.next();
				Packet pkt = (Packet) pairs.getValue();
				
				long interval = TimeUtil.getSeconds() - pkt.m_lTimeStamp;
					
				if (interval >= m_nTimeout)
				{
					iter.remove();
					m_arTimeoutPacket.add(pkt);
				}
			}
						
			if (m_mapPacket.size() > 0)
			{
				m_hanlder.postDelayed(this, 1000);
			}
			
			if (m_arTimeoutPacket.size() > 0)
			{
				for (Packet pkt : m_arTimeoutPacket)
				{
					if (pkt.m_listener != null)
					{
						pkt.m_listener.onTimeout();
					}					
				}
				m_arTimeoutPacket.clear();
			}
		}		
	};

	/**
	 *  
	 * @param pkt
	 * @param repPt : 等待接收封包的pt value
	 * @param listener
	 */
	public void addPacket(BasePOJO pkt, String repPt, IWaitListener listener)
	{
		if (m_nTimeout == 0)
		{
			m_nTimeout = 30000 / 1000;
		}
		
		Packet packet = new Packet(pkt, repPt, listener);
		
		if (m_mapPacket.size() == 0)
		{
			m_hanlder.postDelayed(m_run, 1000);			
		}
		
		m_mapPacket.put(pkt.get_seq(), packet);			
	}
	
	public void checkUpdate(BasePOJO pkt)
	{		
		if (m_mapPacket.size() == 0)
			return;

		Iterator iter = m_mapPacket.entrySet().iterator();
		
		while(iter.hasNext())
		{
			Map.Entry pairs = (Map.Entry)iter.next();
			Packet waitPkt = (Packet) pairs.getValue();
			
			if (pkt.get_seq() == -1 || waitPkt.m_packet.get_seq() == pkt.get_seq())
			{
				if (waitPkt.m_nRspPt.equals(pkt.get_pt()))
				{
					if (waitPkt.m_listener != null)
					{
						iter.remove();					
						waitPkt.m_listener.onStatusOK(pkt);
					}
					break;
				}					
			}
		}
	}

	public void checkUpdate(Return.NormalReturn pkt)
	{
		if (m_mapPacket.size() == 0)
			return;

		Iterator iter = m_mapPacket.entrySet().iterator();

		while(iter.hasNext())
		{
			Map.Entry pairs = (Map.Entry)iter.next();
			Packet waitPkt = (Packet) pairs.getValue();

			if (pkt.getSeq() == -1 || waitPkt.m_packet.get_seq() == pkt.getSeq())
			{
				if (waitPkt.m_nRspPt.equals(pkt.getSeq()))
				{
					if (waitPkt.m_listener != null)
					{
						iter.remove();
						waitPkt.m_listener.onStatusOK(pkt);
					}
					break;
				}
			}
		}
	}

	@Subscribe
	public void onEvent(ConnectManager.Event_LoginConnectClose event)
	{

			clear();
	}
	@Subscribe
	public void onEvent(ConnectManager.Event_ConnectClose event)
	{
			clear();
	}
		
	public static class Packet
	{
		public BasePOJO	m_packet;
		public String			m_nRspPt;
		public long			m_lTimeStamp;
		public IWaitListener m_listener;
		
		public Packet(BasePOJO packet, String pt, IWaitListener listener)
		{
			m_packet = packet;
			m_nRspPt = pt;
			m_listener = listener;
			m_lTimeStamp = TimeUtil.getSeconds();
		}
	}
	
	public abstract class IWaitListener
	{
		abstract void onStatusOK(BasePOJO packet);
		abstract void onStatusOK(Return.NormalReturn packet);
		abstract void onTimeout();
	}
}
